"""
获取当前用户
获取员工
新增员工
删除员工
新增角色
删除角色

"""

from flask_restplus import Resource, Namespace, fields, marshal, reqparse, Model
from common.decorators import catch_error
from app.user import service
from app.user.decorators import token_required
from common.responses import ok
from app.user.model import User
from flask import g
from common import constant
from app.user.model import Role, UserToRole
from common import errors
from app.user import dao
from common.request_parser import get_parser as base_get_parser
from common.response_model import base_model, pagination_model
from app.user.role_controller import role_model
from app.user.decorators import permission_required
from app.user.role_service import PermissionKey
from common.utils import check_phone_number

api = Namespace('user', path='/user')


def get_is_super_admin(obj):
    user = User.query.filter_by(id=obj['id']).first()
    return user.is_super_admin


def get_roles(obj):
    user = User.query.filter_by(id=obj['id']).first()
    return user.roles


# ---------- model -----------
simple_user_model = base_model.inherit('simple_user_model', {
    'id': fields.String(description='user id'),
    'username': fields.String(description='user username'),
    "nickname": fields.String(description='user nickname'),
    "phone": fields.Integer(description='phone'),
    "email": fields.String(description='email'),
    "notes": fields.String(description='notes'),
    'is_active': fields.Boolean(),
    'is_super_admin': fields.Boolean(),
})
user_model = simple_user_model.inherit('user_model', {
    "roles": fields.Nested(role_model)
})

user_dao_model = simple_user_model.inherit('user_dao_model', {
    'is_super_admin': fields.Boolean(
        attribute=lambda obj: get_is_super_admin(obj)),
    'roles': fields.Nested(role_model, attribute=lambda obj: get_roles(obj)),
})

auth_user_model = simple_user_model.inherit("auth_user_model", {
    "permissions": fields.List(fields.String()),
    "roles": fields.Nested(role_model),
})

user_paginate_model = pagination_model.inherit('user_paginate_model', {
    "items": fields.Nested(user_dao_model)
})

user_download_model = api.model('user_download_model', {
    '用户编号': fields.String(attribute='id'),
    '用户名': fields.String(attribute='username'),
    "姓名": fields.String(attribute='nickname'),
    "手机号": fields.Integer(attribute='phone'),
    "邮箱": fields.String(attribute='email'),
    "备注": fields.String(attribute='notes'),
    '部门编号': fields.Integer(attribute='department_id'),
})

put_current_user_parser = reqparse.RequestParser()
put_current_user_parser.add_argument('username', type=str)
put_current_user_parser.add_argument('nickname', help='nickname')
put_current_user_parser.add_argument('email', help='email')
put_current_user_parser.add_argument('notes', help='notes')
put_current_user_parser.add_argument('wechat_id', help='wechat_id')
put_current_user_parser.add_argument('identity', help='identity')
put_current_user_parser.add_argument('join_date', type=str, help='入司时间')


class CurrentUserResource(Resource):
    @catch_error
    @token_required
    def get(self):
        """获取当前用户"""
        user = User.query.filter_by(id=g.user_id).first()
        # todo 把用户权限放进来： user.roles  permissions
        whole_permissions = []
        for role in user.roles:
            whole_permissions += role.permissions
        user.permissions = set(whole_permissions)
        return ok(data={
            **marshal(user, auth_user_model),
        }, message='get current_user successfully')

    @catch_error
    @token_required
    @api.expect(put_current_user_parser)
    def put(self):
        """更新当前用户"""
        user = User.query.filter_by(id=g.user_id).first()
        args = put_current_user_parser.parse_args()
        user.update(**args, commit=True)
        return ok(
            data=marshal(user, simple_user_model),
            message='update current_user successfully')


is_exist_parser = api.parser()
is_exist_parser.add_argument('phone', type=str, help='手机号', required=True)


# 查看手机号是否存在
class IsExistResource(Resource):
    @catch_error
    def get(self):
        args = is_exist_parser.parse_args()
        user = User.query.filter_by(phone=args.get("phone")).first()
        return ok(data={"is_exist": True if user else False}, message="check finished")


IsExistType = constant.IsExistType

is_exist_with_token_parser = api.parser()
is_exist_with_token_parser.add_argument(
    'is_exist_type', type=int, help='字段',
    choices=[ele.value for ele in [
        IsExistType.USER_USERNAME, IsExistType.USER_PHONE, IsExistType.ROLE_NAME]]
)
is_exist_with_token_parser.add_argument('value', type=str, help='值')


# 查看用户名，手机号，角色名称是否存在，
class IsExistWithTokenResource(Resource):
    @catch_error
    @token_required
    def get(self):
        args = is_exist_with_token_parser.parse_args()
        args_type = args.get('is_exist_type')
        value = args.get("value")
        if args_type == IsExistType.USER_PHONE.value:
            obj = User.query.filter_by(phone=value).first()
        elif args_type == IsExistType.USER_USERNAME.value:
            obj = User.query.filter_by(username=value).first()
        elif args_type == IsExistType.ROLE_NAME.value:
            obj = Role.query.filter_by(name=value).first()
        else:
            raise errors.BadRequestError("错误类型, type: {}".format(args_type))
        return ok(data={"is_exist": True if obj else False}, message="check finished")


create_parser = put_current_user_parser.copy()
create_parser.replace_argument('username', type=str, required=True)
create_parser.add_argument('password', type=str, required=True)
create_parser.add_argument('is_active', type=bool, choices=[True, False], help='是否启用')
create_parser.add_argument('role_ids', type=int, help='role_ids', action='append')

get_parser = base_get_parser.copy()


class UsersResource(Resource):
    @catch_error
    @token_required
    @api.expect(create_parser)
    @permission_required(PermissionKey.STAFF_CREATE)
    def post(self):
        args = create_parser.parse_args()
        role_ids = args.pop('role_ids')

        # 检查用户名是否为手机号
        if check_phone_number(args.get("username")):
            raise errors.BadRequestError('用户名不可为手机号')

        # 设置密码
        password = args.pop('password')
        new_user = User.create(**args, commit=True)
        new_user.password = password

        if role_ids:
            service.update_user_to_role(user_id=new_user.id, role_ids=role_ids)
        return ok(data=marshal(new_user, user_model),
                  message='create success')

    @catch_error
    @token_required
    @api.expect(get_parser)
    def get(self):
        args = get_parser.parse_args()
        pagination = dao.get_by_page(**args)
        # 重新根据id获取
        new_items = []
        for item in pagination['items']:
            contract = User.query.filter_by(id=item['id']).first()
            new_items.append(marshal(contract, user_model))
        pagination['items'] = new_items
        return ok(data=pagination,
                  message='get success')


put_parser = create_parser.copy()
put_parser.replace_argument('username', type=str)
put_parser.replace_argument('password', type=str)


class UserResource(Resource):
    @catch_error
    @token_required
    @permission_required(PermissionKey.USER_GET)
    def get(self, obj_id):
        """获取用户详情"""
        obj = User.query.filter_by(id=obj_id).first()
        return ok(data=marshal(obj, user_model),
                  message='get success')

    @catch_error
    @token_required
    @api.expect(put_parser)
    @permission_required(PermissionKey.USER_EDIT)
    def put(self, obj_id):
        """资料修改"""
        args = put_parser.parse_args()
        role_ids = args.pop('role_ids')
        for key in list(args.keys()):
            if args.get(key) is None:
                del args[key]
        obj = User.query.filter_by(id=obj_id).first()

        current_user = User.query.filter_by(id=g.user_id).first()
        # 超级管理员无法被他人修改
        if obj.is_super_admin and (not current_user.is_super_admin):
            raise errors.BadRequestError("无法修改超级管理员信息")
        obj.update(**args, commit=True)

        if role_ids:
            service.update_user_to_role(user_id=obj_id, role_ids=role_ids)
        return ok(data=marshal(obj, user_model),
                  message='update success')

    @catch_error
    @token_required
    @permission_required(PermissionKey.STAFF_DELETE)
    def delete(self, obj_id):
        obj = User.query.filter_by(id=obj_id).first()
        delete_id = obj.hard_delete(commit=True)
        return ok(
            data={'id': delete_id},
            message='delete success')


# ---------- 把路由集中在这里，方便查看 -----------
api.add_resource(CurrentUserResource, '/current_user')
api.add_resource(IsExistResource, '/is_exist')
api.add_resource(IsExistWithTokenResource, '/is_exist_with_token')
api.add_resource(UsersResource, '/users')
api.add_resource(UserResource, '/users/<int:obj_id>')

